package cn.zn.modules.money.cur.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Filter;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.zn.framework.common.exception.RRException;
import cn.zn.framework.common.utils.PageUtils;
import cn.zn.framework.common.utils.Query;
import cn.zn.framework.common.vo.CodeNameVO;
import cn.zn.modules.money.cur.dao.TMoneyInfoDetailMapper;
import cn.zn.modules.money.cur.entity.TMoneyInfo;
import cn.zn.modules.money.cur.entity.TMoneyInfoDetail;
import cn.zn.modules.money.cur.entity.TMoneyInfoDetailAttach;
import cn.zn.modules.money.cur.entity.dto.TempMoneyImportDTO;
import cn.zn.modules.money.cur.service.TMoneyInfoDetailAttachService;
import cn.zn.modules.money.cur.service.TMoneyInfoDetailService;
import cn.zn.modules.money.cur.service.TMoneyInfoService;
import cn.zn.modules.zzsys.inter.SysDicInter;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import lombok.Cleanup;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author zn
 */
@Service
public class TMoneyInfoDetailServiceImpl extends ServiceImpl<TMoneyInfoDetailMapper, TMoneyInfoDetail> implements TMoneyInfoDetailService {

    @Autowired
    private TMoneyInfoDetailAttachService tMoneyInfoDetailAttachService;
    @Autowired
    private TMoneyInfoService tMoneyInfoService;
    @Autowired
    private SysDicInter sysDicInter;
    private final String PROJECT_TYPE_CODE = "zjlyxm";

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        TMoneyInfoDetail tMoneyInfoDetail = BeanUtil.mapToBean(params, TMoneyInfoDetail.class, true);
        IPage<TMoneyInfoDetail> page = new Query<TMoneyInfoDetail>().getPage(params);
        page.setRecords(baseMapper.queryPage(tMoneyInfoDetail, page));
        return new PageUtils(page);
    }

    @Override
    public TMoneyInfoDetail queryDetail(String id) {
        return baseMapper.queryDetail(id);
    }

    @Override
    public void deleteEntity(List<String> ids) {
        // 删除附件
        tMoneyInfoDetailAttachService.remove(new QueryWrapper<TMoneyInfoDetailAttach>().in("T_MONEY_INFO_DETAIL_ID_", ids));
        super.removeByIds(ids);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveAudit(List<String> ids, Boolean result) {
        if (result) {
            this.saveActive(ids);
        } else {
            super.update(new UpdateWrapper<TMoneyInfoDetail>().in("ID_", ids)
                    .set("STATE_", 3)
            );
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveActive(List<String> ids) {
        List<TMoneyInfoDetail> entities = super.list(new QueryWrapper<TMoneyInfoDetail>().in("ID_", ids));
        this.toActive(entities);
    }

    @Override
    public void importDetail(MultipartFile file) {
        try {
            // 从EXCEL中获取数据
            @Cleanup InputStream io = file.getInputStream();
            ExcelReader reader = ExcelUtil.getReader(io, 0, true);
            List<Map<String, Object>> list = reader.readAll();
            final String projectKey = "project";
            final String totalKey = "total";
            final String remarkKey = "remark";
            String projectName = "";
            String remark = "";
            List<TempMoneyImportDTO> tempMoneyImportDTOS = Lists.newArrayList();
            // 查询经费项目
            Map<String, String> projectMap = this.sysDicInter.querySysDicDatas(PROJECT_TYPE_CODE).stream().collect(Collectors.toMap(CodeNameVO::getName, CodeNameVO::getCode, (v1, v2) -> v1));
            for (Map<String, Object> map : list) {
                if (!map.containsKey(projectKey)) {
                    throw new RRException("模板数据错误，请填写“项目名称“");
                }
                if (map.get(projectKey) == null || StrUtil.isBlank(StrUtil.trim(map.get(projectKey).toString()))) {
                    // 未设置经费项目
                    throw new RRException("存在未设置“项目名称”的记录");
                }
                if (map.get(projectKey).equals("项目名称")) {
                    // 跳过标题行
                    continue;
                }
                projectName = StrUtil.trim(map.get(projectKey).toString());
                remark = map.get(remarkKey) == null ? null : map.get(remarkKey).toString().trim();
                Map<String, Object> filterMap = MapUtil.filter(map, (Filter<Map.Entry<String, Object>>) stringObjectEntry -> {
                    // 过滤掉非数值的字段
                    if (stringObjectEntry.getValue() != null
                            && StrUtil.isNotEmpty(stringObjectEntry.getValue().toString())
                            && !StrUtil.equalsIgnoreCase(stringObjectEntry.getKey(), totalKey)
                            && !StrUtil.equalsIgnoreCase(stringObjectEntry.getKey(), projectKey)
                            && !StrUtil.equalsIgnoreCase(stringObjectEntry.getKey(), remarkKey)) {
                        return true;
                    }
                    return false;
                });
                if (filterMap.isEmpty()) {
                    // 跳过没有设置数值的行
                    continue;
                }
                tempMoneyImportDTOS.add(TempMoneyImportDTO.builder()
                        .projectCode(projectMap.containsKey(projectName) ? projectMap.get(projectName) : null)
                        .projectName(projectName)
                        .content(JSONUtil.parseFromMap(filterMap).toString())
                        .remark(remark)
                        .build());
            }
            if (tempMoneyImportDTOS.isEmpty()) {
                throw new RRException("没有需要导入的数据");
            }
            this.baseMapper.createTempMoneyImport();
            this.baseMapper.insertTempMoneyImport(tempMoneyImportDTOS);
        } catch (IOException e) {
            throw new RRException("读取文件内容时出错");
        }
    }

    @Override
    public List<String> queryNoProject() {
        return this.baseMapper.queryNoProject();
    }

    @Override
    public void saveProjectAll() {
        List<String> projects = this.queryNoProject();
        List<CodeNameVO> codeNameVos = sysDicInter.saveSysDicDatas(PROJECT_TYPE_CODE, projects);
        codeNameVos.forEach(o -> {
            this.baseMapper.updateTempMoneyImportProjectCode(o.getCode(), o.getName());
        });
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveAll() {
        List<TempMoneyImportDTO> dtos = this.baseMapper.selectTempMoneyImport();
        List<TMoneyInfoDetail> list = Lists.newArrayList();
        dtos.forEach(o -> {
            JSONObject jsonObject = JSONUtil.parseObj(o.getContent());
            jsonObject.entrySet().forEach(item -> {
                TMoneyInfoDetail entity = new TMoneyInfoDetail();
                entity.setProjectCode(o.getProjectCode());
                entity.setCateCode(item.getKey());
                entity.setMoney(NumberUtil.toBigDecimal(item.getValue().toString()).setScale(2).doubleValue());
                entity.setRemark(o.getRemark());
                entity.setState(0);
                list.add(entity);
            });
        });
        super.saveBatch(list);
    }

    private void toActive(List<TMoneyInfoDetail> details) {
        details.stream().forEach(o -> {
            super.update(new UpdateWrapper<TMoneyInfoDetail>().eq("ID_", o.getId())
                    .set("STATE_", 2)
            );
            TMoneyInfo tMoneyInfo = tMoneyInfoService.getOne(new QueryWrapper<TMoneyInfo>()
                    .eq("MONEY_TYPE_CODE_", o.getMoneyTypeCode())
                    .eq("PROJECT_CODE_", o.getProjectCode())
                    .eq("CATE_CODE_", o.getCateCode())
                    .ge("TOTAL_MONEY_", 0)
            );
            if (tMoneyInfo == null) {
                tMoneyInfo = new TMoneyInfo();
                BeanUtil.copyProperties(o, tMoneyInfo);
                tMoneyInfo.setId(null);
                tMoneyInfo.setTotalMoney(o.getMoney());
                tMoneyInfoService.save(tMoneyInfo);
            } else {
                tMoneyInfoService.update(new UpdateWrapper<TMoneyInfo>().eq("ID_", tMoneyInfo.getId())
                        .set("TOTAL_MONEY_", NumberUtil.add(o.getMoney(), tMoneyInfo.getTotalMoney()))
                );
            }
        });
    }
}
